﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using KonachanChanger.Forms;
using KonachanChanger.Data;
using KonachanChanger.API;
using System.Diagnostics;

namespace KonachanChanger
{
    public partial class Form1 : Form
    {
        int[] minutesarray = new int[] { 1, 5, 10, 30, 60, 120, 180, 360, 720, 1440 };
        posts Posts = null;
        Search search = new Search();

        private bool browsemode = false;
        public void SetBrowseMode(string search)
        {
            browsemode = true;
            textBox1.Text = search;             
            if (this.Visible)
                Form1_Load(this, new EventArgs());

        }

        #region Loading and Unloading...
        public Form1()
        {
            InitializeComponent();
            trackBar1.Maximum = minutesarray.Length - 1;
            trackBar1_ValueChanged(this, new EventArgs());
        }
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (browsemode)
                return;
            var prefs = LocalDb.GetInstance().Prefs;
            prefs.SafeSearch = SafeSearchCheckbox.CheckState;
            prefs.LastSearch = textBox1.Text;
            prefs.MinutesSliderValue = trackBar1.Value;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            if (browsemode)
            {
                trackBar1.Visible = false;
                WallpaperTimer.Enabled = false;
                IntervalLabel.Visible = false;
            }
            else
            {
                var prefs = LocalDb.GetInstance().Prefs;
                textBox1.Text = prefs.LastSearch;
                SafeSearchCheckbox.CheckState = prefs.SafeSearch;
                trackBar1.Value = prefs.MinutesSliderValue;
            }
            if (textBox1.Text != "")
            {
                try
                {
                    doSearch();
                }
                catch (Exception v)
                {
                    MessageBox.Show(v.ToString());
                }
                if (!browsemode)
                    timer1_Tick(this, new EventArgs());
            }
        }

        #endregion


        private void SearchButton_Click(object sender, EventArgs e)
        {
            flowLayoutPanel1.Controls.Clear(); 
            doSearch();
            //if (Posts.count > 0)
            //    getNextPreview();
            
        }

        private void doSearch()
        {
            Posts = new posts();
            Posts.Posts = new post[] { };
            search = new Search();
            search.tags = textBox1.Text;
            if (!search.tags.Contains("rating:") && SafeSearchCheckbox.CheckState == CheckState.Checked)
                search.tags += " rating:s";
            if (!search.tags.Contains("rating:") && SafeSearchCheckbox.CheckState == CheckState.Indeterminate)
                search.tags += " -rating:e";
            if (!search.tags.Contains("censored"))
                search.tags += " -censored";  // Remove the pixelation, please.
            search.RegisterCallback(this.NewPost);
            ThreadPool.QueueUserWorkItem((x) =>
            {
                foreach (post p in LocalDb.GetInstance().LocalSearch(search.tags).Posts)
                {
                    NewPost(p, search);
                }
            }
            );

            WaitCallback get = null;
            get = new WaitCallback((o) =>
            {
                try
                {
                    Posts = search.getPosts();
                    this.Invoke(new Action(() => toolStripStatusLabel1.Text = Posts.count + " images."));
                }
                catch (System.Net.WebException)
                {
                    Thread.Sleep(5000);
                    ThreadPool.QueueUserWorkItem(get);
                }
                catch (InvalidOperationException)
                {
                    Thread.Sleep(60000);
                    ThreadPool.QueueUserWorkItem(get);
                }
            });
            ThreadPool.QueueUserWorkItem(get);
            getNextPreview();
        }
        
        private void NewPost(post post, Search source)
        {
            if (source != search)
                return;
            if (LocalDb.GetInstance().BlockedIds.Contains(post.id))
                return;
            if (Posts.Posts.Contains(post))
                return;
            Posts.Posts = Posts.Posts.Union(new post[] { post }.ToList()).ToArray();
            Queue.Add(post);
            getNextPreview();
            if (!this.IsDisposed)
                this.Invoke(new Action(() => toolStripStatusLabel1.Text = Posts.count + " images."));
            
        }
        
        List<post> Queue = new List<post>();
        
        private void getNextPreview() 
        {
            post next;
            lock (Queue)
            {
                next = Queue.FirstOrDefault();
                if (next != null)
                    Queue.Remove(next);
            }
            if (this.Disposing || this.IsDisposed)
                return;
            if (next != null)
            {
                if (search.MatchesRating(next) && !this.IsDisposed)
                    this.Invoke(new Action(() => DisplayNewPost(next)));
            }
            //if (Posts == null) 
            //    return;
            //toolStripStatusLabel1.Text = "Showing " + flowLayoutPanel1.Controls.Count + " of " + Posts.count + " (" + search.NumLoaded + " loaded, " + search.NumBlocked + " blocked)";
            //if(Posts.Posts == null)
            //    return;
            //if (previewIndex == Posts.Posts.Length - 1)
            //{
            //    if (Posts.Finished)
            //        return;
            //    search.page++;
            //    try
            //    {
            //        Posts.Union(search.getPosts());
            //    }
            //    catch
            //    { search.page--; }
            //    //if (Posts.Posts == null)
            //    if (previewIndex == Posts.Posts.Length - 1)
            //        return;
            //    //previewIndex = -1;
            //    //toolStripStatusLabel1.Text = "Got page " + search.page;
            //}
            //post Post = ((post)Posts.Posts[++previewIndex]);
            //DisplayNewPost(Post);
        }

        private void DisplayNewPost(post Post)
        {
            PictureBox box = new PictureBox();
            box.Width = Post.preview_width;
            box.Height = Post.preview_height;
            box.SizeMode = PictureBoxSizeMode.AutoSize;
            box.ImageLocation = Post.ThumbnailPath();
            box.Visible = true;
            box.Tag = Post;
            box.Name = "Loading";
            flowLayoutPanel1.Controls.Add(box);
            box.LoadCompleted += new AsyncCompletedEventHandler(box_LoadCompleted);
            box.DoubleClick += new EventHandler(box_DoubleClick);
            box.MouseClick += new MouseEventHandler(box_MouseClick);
        }

        void box_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Right)
            {
                ThumbnailRightClickMenu.Tag = sender; 
                
                PictureBox box = (PictureBox)sender;
                post Post = (post)box.Tag;

                contextRating.Text = "Rating: " + Post.rating;
                contextId.Text = "Id: " + Post.id;
                contextTags.DropDownItems.Clear();
                foreach (string tag in Post.Tags)
                {
                    ToolStripMenuItem menuitem = new ToolStripMenuItem();
                    menuitem.Text = tag;
                    menuitem.Click += new EventHandler(TagToolStripMenuItem_Click);
                    contextTags.DropDownItems.Add(menuitem);
                }
                
                
                
                ThumbnailRightClickMenu.Show(box, e.Location);
            }
        }

        void box_DoubleClick(object sender, EventArgs e)
        {
            post Post = ((post)((PictureBox)sender).Tag);
            new Thread(new ThreadStart(Post.SetWallpaper)).Start();
            //Post.SetWallpaper();
        }

        void box_LoadCompleted(object sender, AsyncCompletedEventArgs e)
        {
            ((PictureBox)sender).Name = ((post)((Control)sender).Tag).tags;
            //if (flowLayoutPanel1.VerticalScroll.Value == flowLayoutPanel1.VerticalScroll.Maximum || flowLayoutPanel1.VerticalScroll.Visible == false)
            //    flowLayoutPanel1_Scroll(this, new ScrollEventArgs(ScrollEventType.SmallIncrement, flowLayoutPanel1.VerticalScroll.Value));
            getNextPreview();
        }

        private void flowLayoutPanel1_Scroll(object sender, ScrollEventArgs e)
        {
            //if (flowLayoutPanel1.Controls.Count > 4 && flowLayoutPanel1.Controls[flowLayoutPanel1.Controls.Count - 4].Name == "Loading")
            //    return;
            //toolStripStatusLabel1.Text = "Scroll " + e.NewValue + "/" + flowLayoutPanel1.VerticalScroll.Maximum;
            ////if (e.NewValue > flowLayoutPanel1.VerticalScroll.Maximum - flowLayoutPanel1.Height - 400 || flowLayoutPanel1.VerticalScroll.Visible == false)
            ////{
            //    getNextPreview();
            ////}
        }

        private void toolStripPreviewNext_ButtonClick(object sender, EventArgs e)
        {
            //getNextPreview();
            timer1_Tick(this, new EventArgs());
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (Posts == null)
                return;
            //new Thread(new ThreadStart(SetRandomWallpaper)).Start();
            ThreadPool.QueueUserWorkItem((o) => SetRandomWallpaper());
            //if (!Posts.Finished) // TODO: The Culprit
            //{
            //    search.page++;
            //    try
            //    {
            //        Posts.Union(search.getPosts());
            //    }
            //    catch
            //    { search.page--; }
            //}
        }

        public void SetRandomWallpaper()
        {
            // TODO: Better offline wallpaper selection!
            // If compter  is offline, and randomly selects unavailable wallpaper, 
            // it skips and does nothing until next tick.
            // This could mean up to three days before change.  This be bad!
            if (Posts.NextRandomWallpaper != null)
            {
                Posts.NextRandomWallpaper.SetWallpaper();
                Posts.NextRandomWallpaper = null;
            }
            else{
                try
                {
                    Posts.RandomPost.SetWallpaper();
                }
                catch (NullReferenceException)
                { }
                Posts.NextRandomWallpaper = null;
            }
        }

       
        private void blockImageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            PictureBox box = (PictureBox)ThumbnailRightClickMenu.Tag;
            post Post = (post)box.Tag;

            Post.BlockPost();
            flowLayoutPanel1.Controls.Remove(box);
        }

        private void viewOnWebsiteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ((post)(((Control)ThumbnailRightClickMenu.Tag).Tag)).OpenPage();
        }
    
        private void trackBar1_ValueChanged(object sender, EventArgs e)
        {
            double minutes = minutesarray[trackBar1.Value];
            TimeSpan span = TimeSpan.FromMinutes(minutes);
            IntervalLabel.Text = span.ToReadableString();
            WallpaperTimer.Interval = Convert.ToInt32(span.TotalMilliseconds);
        }

        private void TagToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //new Thread(new ThreadStart(() => {
                ToolStripMenuItem menuItem = sender as ToolStripMenuItem;
                string tag = menuItem.Text;
                // You clicked a tag!  
                var form = new Form1();
                form.SafeSearchCheckbox.CheckState = this.SafeSearchCheckbox.CheckState;
                form.SetBrowseMode(tag);
                form.Show();
            //})).Start();
        }

        #region Tray Icon
        private void Form1_Resize(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized)
            {
                this.Hide(); 
            }
        }

        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            this.Show();
            this.WindowState = FormWindowState.Normal;
        }
        #endregion

        private void notifyIcon1_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Right)
            {
                TrayContextMenu.Show(Cursor.Position);
            }
        }

        private void toolStripMenuItem1_Click(object sender, EventArgs e)
        {
            new PropertyForm(LocalDb.GetInstance().Prefs, this).Show();
        }

        private void assignCustomTagToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var post = ((post)(((Control)ThumbnailRightClickMenu.Tag).Tag));
            var form = new TagEditorForm(post.id);
            var res = form.ShowDialog();
            string[] Tags = form.Tags;

        }

        private void showInExplorerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var path =((post)(((Control)ThumbnailRightClickMenu.Tag).Tag)).SearchFile(false);
            if (System.IO.File.Exists(path))
            {
                Process.Start("explorer.exe", String.Format("/select,\"{0}\"", path));
            }
        }
    }
}
